// ==UserScript==
// @name         sf-express-phone
// @version      2024-03-12
// @description  sf-express get phone
// @author       aofall
// @match        https://www.sf-express.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    let stop = false;
    let login = true;
    let phoneArr = [];
    let noArr = [];
    // 触发事件
    window.addEventListener('load', function () {
        createExportButton();
    }, false);

    // 获取Cookie
    function getCookie() {
        if (document.cookie.length > 0) {
            console.log(document.cookie);
            return document.cookie;
        }
        return ""
    }
    // 初始化导出按钮
    function createExportButton() {
        const exportButton = document.createElement('button');
        exportButton.textContent = '导出手机号';
        exportButton.style.position = 'fixed';
        exportButton.style.top = '0px';
        exportButton.style.right = '10px';
        exportButton.style.zIndex = '9999';
        exportButton.addEventListener("click", function() {
            handleExportClick();
        });
        document.body.appendChild(exportButton);
        const stopButton = document.createElement('button');
        stopButton.textContent = '停止导出';
        stopButton.style.position = 'fixed';
        stopButton.style.top = '20px';
        stopButton.style.right = '10px';
        stopButton.style.zIndex = '9999';
        stopButton.addEventListener("click", function() {
            handleStopClick();
        });
        document.body.appendChild(stopButton);
    }
    function handleStopClick() {
        stop = true;
    }
    // 处理点击事件
    async function handleExportClick() {
        // 每次点击按钮都清空
        if (getCookie() === "") {
            window.alert("当前可能未登录");
            return;
        }
        stop = false;
        phoneArr = [];
        noArr = [];
        const dateIn = window.prompt("输入完整日期，例如 2024-03-08，如果没有输入则获取所有订单（由于顺丰限制最多只能获取最近三个月的订单）");
        let valid = new Date(dateIn);
        if (dateIn) {
            if (valid.toString() === 'Invalid Date') {
                window.alert("输入的日期不合法");
                return;
            } else {
                console.log("开始获取,日期为：" + valid.toLocaleDateString());
            }
        }
        console.log("正在获取总分页");
        let totalPage, firstPageData, dataCount;
        // 获取总分页数
        if (dateIn) {
            let page = await getPage(1, dateIn);
            totalPage = page.result.totalPage;
            firstPageData = page.result.data;
            dataCount = page.result.sendTotal;
        } else {
            let page = await getPage(1);
            totalPage = page.result.totalPage;
            firstPageData = page.result.data;
            dataCount = page.result.sendTotal;
        }
        if (!login) {
            window.alert("当前可能未登录");
        }
        console.log("每页50条，共有" + totalPage + "页的数据，共有" + dataCount + "条数据");
        // 处理掉第一页的内容
        handlePage(firstPageData);
        // 获取剩下的页数
        for(let i = 2; i < totalPage; i++) {
            if (stop) {
                console.log("停止获取");
                break;
            }
            console.log("正在获取分页" + i);
            //createPrompt("正在获取分页" + i);
            let pageData;
            if (dateIn) {
                pageData = await getPage(i, dateIn);
            } else {
                pageData = await getPage(i);
            }
            // 处理剩下分页的内容
            handlePage(pageData.result.data);
            let time = getRandomInt(1000,3000);
            console.log("休眠" + time + "毫秒");
            await sleep(time);
        }
        // 根据单号数组去取手机号
        for (const item of noArr) {
            if (stop) {
                console.log("停止获取");
                break;
            }
            console.log("正在获取单号" + item);
            try {
                let detailData = await getResult(item);
                handleDetail(detailData);
                let time = getRandomInt(1000,3000);
                console.log("获取单号 " + item + " 信息完成。休眠" + time + "毫秒");
                await sleep(time);
            } catch (error) {
                console.log("获取单号" + item + "出错")
                console.error(error);
            }
        }
        console.log("获取完成");
        if (phoneArr.length === 0) {
            window.alert("没有获取到符合条件的数据，该日无快递或日期填写不正确，需要填写完整日期如 2024-03-08，其中的0不可忽略");
        } else {
            console.log("获取到" + phoneArr.length + "条数据，开始导出");
            exportFile(phoneArr, dateIn);
        }
    }
    // 获取寄件分页数据
    async function getPage(pageNo, time) {
        const url = "https://www.sf-express.com/sf-service-core-web/service/waybillList/getPaginatedWaybillList?lang=sc&region=cn&translate=sc";
        // dataType 0为寄件 1为收件
        let bodyInfo;
        if (time) {
            bodyInfo = {"pageNo": pageNo,"pageSize": 50,"condition": {"dataType": 0,"supportWaybillStatusNew": true,"startTm": time,"endTm": time}};
        } else {
            bodyInfo = {"pageNo": pageNo,"pageSize": 50,"condition": {"dataType": 0,"supportWaybillStatusNew": true}};
        }
        const jsonData = JSON.stringify(bodyInfo);
        let result = {};
        await fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: jsonData
        }).then(response => {
            if (response.ok) {
                return response.json();
            } else {
                console.error(response)
            }
            throw new Error('本机网络异常/顺丰服务器异常/脚本需要更新了');
        }).then(data => {
            result = data;
            if (result.success === false && result.code === 121) {
                login = false;
            } else {
                login = true;
            }
        }).catch(error => {
            console.error('There has been a problem with your fetch operation:', error)
        });
        return result;
    }
    // 获取寄件详细信息
    async function getResult(number) {
        let result = {};
        const url = "https://www.sf-express.com/sf-service-core-web/service/waybill/" + number + "/electronicStub?lang=sc&region=cn&translate=";
        await fetch(url, {
            method: 'GET'
        }).then(function(response) {
            if (response.ok) {
                return response.json();
            } else {
                console.error(response)
                throw new Error('本机网络异常/顺丰服务器异常/脚本需要更新了');
            }
        }).then(function(data) {
            result = data;
        });
        return result;
    }
    // 将分页信息中的单号取出到全局数组
    function handlePage(data) {
        data.forEach((item) => {
            //console.log(item.waybillno);
            if (item.waybillno) {
                noArr.push(item.waybillno);
            }
        });
    }
    // 将详细信息中的手机号取出
    function handleDetail(data) {
        if (data.result.addresseePhone) {
            phoneArr.push(data.result.addresseePhone);
        } else {
            console.log("单号" + data.result.waybillNo + "中获取不到手机号");
        }
    }
    // 生成随机休眠时间
    function getRandomInt(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    // 休眠
    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    // 导出文件
    function exportFile(data, time) {
        let csvContent = '';
        data.forEach((item) => {
            csvContent += item += `\n`;
        });
        const uri = 'data:text/txt;charset=utf-8,\ufeff' + encodeURIComponent(csvContent);
        const link = document.createElement("a");
        link.href = uri;
        let fileName = "导出手机号-";
        if (time) {
            const date = new Date(time); // 创建一个表示当前时间的Date对象
            const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
            fileName = fileName + formattedDate + ".txt";
        } else {
            fileName = fileName + "全部.txt";
        }
        link.download = fileName;
        link.click();
    }
})();